#include <GameEngine/GameEngine/hex_map_renderer.h>

#include <GameEngine/Maps/map_cell.h>
#include <GameEngine/Maps/terrain_descriptor.h>
#include <GameEngine/Geometry/Location/vector2d.h>
#include <GameEngine/Geometry/Surfaces/parallelogram3d.h>
#include <GameEngine/Graphics/Texture/texture_coordinates.h>

#include <QtGui/QImage>
#pragma warning( push )
#pragma warning( disable : 4312 )
#include <QtOpenGL/QGLContext>
#pragma warning( pop )

#include <iostream>

#ifndef DOXYGEN_IGNORE


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif


//! Default constructor
HexMapRenderer::HexMapRenderer() : map_(nil), SceneElement(GeometryOpaqueElement) {}

//! Build the rendering
/*!
 @param map The hexagonal map to render
 */
void HexMapRenderer::build(const HexMap& map, std::list<HexMapSearch::Node>* path) {
	// Get map
	map_ = &map;

	// Check path
	if ( path != nil ) {
		if ( path->empty() ) path = nil;
	}

	// Get OpenGL context
	QGLContext* context = const_cast<QGLContext*>(QGLContext::currentContext());

	// Read wall texture
	QImage img; img.load("..\\GameEngineMisc\\data\\images\\political_world_map.jpg");
	map_texture_.set_texture(context, img);
	map_texture_.set_parameters(Texture::UseMipmapMode);
	map_texture_.set_parameters(Texture::ModulateMode);
	map_texture_.set_parameters(Texture::RepeatMode);
	map_texture_.set_parameters(Texture::LinearMagFilter);
	map_texture_.set_parameters(Texture::LinearMipmapLinearMinFilter);
	map_texture_.unbind_texture();

	// Draw the map in the display list
	list_.begin_display_list();

	// Enable 2D texture
	glEnable(GL_TEXTURE_2D);
	map_texture_.bind_texture();

	// Draw box
	const Parallelogram2d<float>& box = map.map_box();
	Point2d<float> pts[] = {
		box[Parallelogram2D::First],
		box[Parallelogram2D::Second],
		box[Parallelogram2D::Third],
		box[Parallelogram2D::Fourth]
	};
	glColor3f(1,1,1);
	glNormal3f(0,0,1);
	glBegin(GL_QUADS);
		glTexCoord2f(1,1); glVertex2f(pts[0].x(),pts[0].y());
		glTexCoord2f(0,1); glVertex2f(pts[1].x(),pts[1].y());
		glTexCoord2f(0,0); glVertex2f(pts[3].x(),pts[3].y());
		glTexCoord2f(1,0); glVertex2f(pts[2].x(),pts[2].y());
	glEnd();

	// Remove texture
	map_texture_.unbind_texture();

	// Draw the path
	if ( path != nil ) {
		// Useful variables
		Map::MapIndex x, y;
		Point2d<float> prev_pos;
		int index = 0;
		float nb_nodes = (float)path->size();
		glLineWidth(5);

		// Iterate over the path
		for ( std::list<HexMapSearch::Node>::iterator it = path->begin(); it != path->end(); ++it ) {
			// Get current node
			map.get_axes_indexes(x,y,*it);

			// Get node position
			float xval = (float)( 1+2*x ) / (float)( 2*map.width() );
			float yval = (float)( (x % 2) + 1 + 2*y ) / (float)( 1+2*map.height() );
			Point2d<float> pos = map.map_box().point( Coords2d<float>(xval,yval) );

			if ( index ) {
				float height = 0.001f;
				float col = (float)index/(float)(nb_nodes-1);
				glBegin(GL_LINES);
					glVertex3f(prev_pos.x(), prev_pos.y(), height);
					glColor3f( 1.0f-col, 1.0f-col, 1 );
					glVertex3f(pos.x(), pos.y(), height);
				glEnd();
			}
			else {
				glColor3f( 1, 1, 1 );
			}
			++index;
			prev_pos = pos;
		}
	}

	// Finish the drawing
	list_.end_display_list();
}

//! Destructor
HexMapRenderer::~HexMapRenderer() {}

//! Draw the map
/*!
 @param ray The picking ray under the mouse
 @return Always return true
 */
bool HexMapRenderer::draw(const Line3d<float>& ray) {
	// Draw the whole map
	list_.draw();

	// Test cell under the picking location
	float line_coordinate = ray.p1().z() / ( ray.p1().z() - ray.p2().z() );
	Point3d<float> pt = ray.point(line_coordinate);
	std::vector< Point2d<float> > cell = map_->get_cell_geometry( Point2d<float>(pt.x(), pt.y()) );

	// Draw the cell wireframe if there is such a cell
	if ( cell.empty() == false ) {
		float height = 0.0001f;
		glColor3f(1,0,0);
		glBegin(GL_LINE_STRIP);
			for ( unsigned int k = 0; k < cell.size(); ++k ) {
				glVertex3f(cell[k].x(),cell[k].y(),height);
			}
			glVertex3f(cell[0].x(),cell[0].y(),height);
		glEnd();
	}
	return true;
}



#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#endif
